(*DONT_TOUCH = "TRUE"*)
module multi_lia_top# (
    parameter datin_width = 8,
    parameter daout_width = 16,
    parameter mux_num = 1536,
    parameter work_clk_freq = 100_000_000
)
(
    input sys_clk,
    input rst_n,

    output scl,
    inout sda,
    input CLK_TX,

    input CNT_VLD,
    input [7:0] pixel_so_in,
    input TRIGGER,
    output CHIP_EN,
    output CLK_OUT,
    output CI_CTRL,
    input INT,


    output ttl_signal,
    input rx,
    output tx,
    output uart_led
);

function integer clogb2(input integer depth);
  integer tmp;
  begin
    tmp = depth;
    for (clogb2 = 0; tmp > 0; clogb2 = clogb2 + 1) 
      tmp = tmp >> 1;                          
  end
endfunction

wire work_clk;
wire locked;

//wlk control
clk_ctrl u_clk_ctrl(
    .resetn(rst_n),
    .clk_in1(sys_clk),
    .locked(locked),
    .clk_out1(ad_clk_50m),
    .clk_out2(work_clk)
);

wire [7:0] sin_ref;
wire [7:0] cos_ref;

//dds控制
dds_ctrl #(
    .work_clk(work_clk_freq),
    .ttl_freq(500)
) u_dds_ctrl(
    .clk(work_clk),
    .rst_n(rst_n),
    .ttl(ttl_signal),
    .sin_ref(sin_ref),
    .cos_ref(cos_ref)
);

wire datin_bram_w_en;
(* mark_debug="true" *) wire [clogb2(mux_num) - 1:0] datin_bram_w_addr; //clogb2(mux_num) - 1:0
(* mark_debug="true" *) wire [datin_width - 1 : 0] datin_bram_w_data;
wire datin_bram_w_we;
wire start_single;
wire start_ref_lock;

wire pcl7152_busy;
wire [7:0] error_cnt;
wire error_rst;
wire bram_clk;

//pcl7152
pcl7152_top u_pcl7152_top(
    .clk(sys_clk), // FPGA 50MHz
    .rst_n(rst_n),
    .scl(scl),
    .sda(sda),
    .CLK_TX(CLK_TX),
    .CNT_VLD(CNT_VLD),
    .pixel_so_in(pixel_so_in),
    .TRIGGER(TRIGGER),
    .CHIP_EN(CHIP_EN),
    .CLK_OUT(CLK_OUT),
    .CI_CTRL(CI_CTRL),
    .INT(INT),
    .bram_clk(bram_clk),
    .datin_bram_w_addr(datin_bram_w_addr),
    .datin_bram_w_data(datin_bram_w_data),
    .datin_bram_w_en(datin_bram_w_en),
    .datin_bram_w_we(datin_bram_w_we),
    .busy(pcl7152_busy),
    .error_cnt(error_cnt),
    .error_rst(error_rst)
);

wire pulse_out;
negedge_pulse u_negedge_pulse(
    .clk(work_clk),
    .rst_n(rst_n),
    .data_in(pcl7152_busy),
    .pulse_out(pulse_out)
);

assign start_single = pulse_out;
assign start_ref_lock = pulse_out;


wire [datin_width - 1 : 0] datin_bram_r_data;
wire datin_bram_r_en;
wire [clogb2(mux_num) - 1 : 0] datin_bram_r_addr;

wire [daout_width - 1 : 0] daout_bram_w_sin_data;
wire [clogb2(mux_num) - 1 : 0] daout_bram_w_sin_addr;
wire [daout_width - 1 : 0] daout_bram_w_cos_data;
wire [clogb2(mux_num) - 1 : 0] daout_bram_w_cos_addr;
wire daout_bram_w_sin_en;
wire daout_bram_w_cos_en;
wire daout_bram_w_sin_we;
wire daout_bram_w_cos_we;

wire update_flag;

multi_iir_top #(
    .ref_width(8),
    .datin_width(datin_width),
    .daout_width(daout_width),
    .mux_num(mux_num) //mux_num
) u_multi_iir_top  (
    .clk(work_clk),
    .rst_n(rst_n),

    .sin_ref(sin_ref),
    .cos_ref(cos_ref),

    .datin_bram_r_data(datin_bram_r_data),
    .datin_bram_r_en(datin_bram_r_en),
    .datin_bram_r_addr(datin_bram_r_addr),

    .daout_bram_w_sin_data(daout_bram_w_sin_data),
    .daout_bram_w_sin_we(daout_bram_w_sin_we),
    .daout_bram_w_sin_en(daout_bram_w_sin_en),
    .daout_bram_w_sin_addr(daout_bram_w_sin_addr),

    .daout_bram_w_cos_data(daout_bram_w_cos_data),
    .daout_bram_w_cos_we(daout_bram_w_cos_we),
    .daout_bram_w_cos_en(daout_bram_w_cos_en),
    .daout_bram_w_cos_addr(daout_bram_w_cos_addr),

    .start(start_single),
    .start_ref_lock(start_ref_lock),
    .update_flag(update_flag)
);

//datin_bram 缓存读入的n路数据
datin_bram u_datin_bram(
    .clka(bram_clk),    // input wire clka 从ad写入
    .ena(datin_bram_w_en),      // input wire ena
    .wea(datin_bram_w_we),      // input wire [0 : 0] wea
    .addra(datin_bram_w_addr),  // input wire [ : 0] addra
    .dina(datin_bram_w_data),    // input wire [7 : 0] dina

    .clkb(work_clk),    // input wire clkb 读取
    .enb(datin_bram_r_en),      // input wire enb
    .addrb(datin_bram_r_addr),  // input wire [ : 0] addrb
    .doutb(datin_bram_r_data)  // output wire [7 : 0] doutb
);

//daout_bram 缓存输出的n路数据
wire [clogb2(mux_num) - 1 : 0] daout_bram_r_sin_addr;
wire [clogb2(mux_num) - 1 : 0] daout_bram_r_cos_addr;
wire [15:0] daout_bram_r_sin_data;
wire [15:0] daout_bram_r_cos_data;
wire daout_bram_r_sin_en;
wire daout_bram_r_cos_en;

//daout_bram 缓存输出的n路数据
datout_bram u_datout_bram_sin (
  .clka(work_clk),    // input wire clka 写入
  .ena(daout_bram_w_sin_en),      // input wire ena
  .wea(daout_bram_w_sin_we),      // input wire [0 : 0] wea
  .addra(daout_bram_w_sin_addr),  // input wire [10 : 0] addra
  .dina(daout_bram_w_sin_data),    // input wire [15 : 0] dina

  .clkb(work_clk),    // input wire clkb 读取
  .enb(daout_bram_r_sin_en),      // input wire enb
  .addrb(daout_bram_r_sin_addr),  // input wire [10 : 0] addrb
  .doutb(daout_bram_r_sin_data)  // output wire [15 : 0] doutb
);

datout_bram u_datout_bram_cos (
  .clka(work_clk),    // input wire clka 写入
  .ena(daout_bram_w_cos_en),      // input wire ena
  .wea(daout_bram_w_cos_we),      // input wire [0 : 0] wea
  .addra(daout_bram_w_cos_addr),  // input wire [10 : 0] addra
  .dina(daout_bram_w_cos_data),    // input wire [15 : 0] dina

  .clkb(work_clk),    // input wire clkb 读取
  .enb(daout_bram_r_cos_en),      // input wire enb
  .addrb(daout_bram_r_cos_addr),  // input wire [10 : 0] addrb
  .doutb(daout_bram_r_cos_data)  // output wire [15 : 0] doutb
);
wire [15:0] result_bram_w_data;
wire [clogb2(mux_num) - 1 : 0] result_bram_w_addr;
wire result_bram_w_en;
wire result_bram_w_we;

wire codic_busy;
codic_process u_codic_process (
    .clk(work_clk),
    .rst_n(rst_n),

    .daout_bram_r_sin_data(daout_bram_r_sin_data),
    .daout_bram_r_sin_addr(daout_bram_r_sin_addr),
    .daout_bram_r_sin_en(daout_bram_r_sin_en),

    .daout_bram_r_cos_data(daout_bram_r_cos_data),
    .daout_bram_r_cos_addr(daout_bram_r_cos_addr),
    .daout_bram_r_cos_en(daout_bram_r_cos_en),

    .result_bram_w_data(result_bram_w_data),
    .result_bram_w_addr(result_bram_w_addr),
    .result_bram_w_en(result_bram_w_en),
    .result_bram_w_we(result_bram_w_we),

    .start_flag(update_flag),
    .busy(codic_busy)
);

wire [15:0] result_bram_r_data;
wire [clogb2(mux_num) - 1 : 0] result_bram_r_addr;
wire result_bram_r_en;

result_bram u_result_bram (
  .clka(work_clk),    // input wire clka
  .ena(result_bram_w_en),      // input wire ena
  .wea(result_bram_w_we),      // input wire [0 : 0] wea
  .addra(result_bram_w_addr),  // input wire [10 : 0] addra
  .dina(result_bram_w_data),    // input wire [15 : 0] dina

  .clkb(work_clk),    // input wire clkb
  .enb(result_bram_r_en),      // input wire enb
  .addrb(result_bram_r_addr),  // input wire [10 : 0] addrb
  .doutb(result_bram_r_data)  // output wire [15 : 0] doutb
);

wire tx;
wire [$clog2(mux_num) - 1 : 0] uart_mux_index;
uart_transceiver #(
    .mux_num(mux_num),
    .work_clk_freq(work_clk_freq)
) u_uart_transceiver(
    .clk(work_clk),
    .rst_n(rst_n),
    .rx(rx),
    .tx(tx),

    .result_bram_r_data(result_bram_r_data),
    .result_bram_r_addr(result_bram_r_addr),
    .result_bram_r_en(result_bram_r_en),

    .busy(uart_led),
    .mux_index(uart_mux_index)
);

endmodule